﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MH.Lib.Actions;

namespace MH.Lib.Data
{
    public class PersonContainer
        : IPersonContainer
    {
        #region IPersonContainer

        /// <summary>
        /// Attempts to insert person to this container
        /// </summary>
        /// <param name="person"> Person data to insert </param>
        /// <returns> True if successful, false otherwise </returns>
        public bool Insert(IPerson person)
        {
            if (Contains(person.ID))
                return false;

            try
            {
                m_impl.Add(person.ID, person);
            }
            catch (Exception)
            {
                return false;
            }

            return true;
        }

        /// <summary>
        /// Determines whether person data with given ID exists in this container
        /// </summary>
        /// <param name="ID"> ID to look for </param>
        /// <returns> True if successful, false otherwise </returns>
        public bool Contains(string ID)
        {
            return Find(ID) != null;
        }

        /// <summary>
        /// Attempts to find person data according to given ID
        /// </summary>
        /// <param name="ID"> ID to look for </param>
        /// <returns> Person data of found, null otherwise </returns>
        public IPerson Find(string ID)
        {
            IPerson person;
            if(!m_impl.TryGetValue(ID, out person))
                return null;

            return person;
        }

        /// <summary>
        /// Attempts to remove person from this container
        /// </summary>
        /// <param name="ID"> ID to look for </param>
        /// <returns> True if successful, false otherwise </returns>
        public bool Remove(string ID)
        {
            if (!Contains(ID))
                return false;

            try
            {
                return m_impl.Remove(ID);
            }
            catch (Exception)
            {
                return false;
            }
        }

        /// <summary>
        /// Clears this container
        /// </summary>
        public void Clear()
        {
            m_impl.Clear();
        }

        /// <summary>
        /// Attempts to apply given action for each person in this container
        /// </summary>
        /// <param name="action"> Action to apply </param>
        /// <returns> True if successful, false otherwise </returns>
        public bool ApplyAll(IAction action)
        {
            bool res = true;
            foreach (IPerson person in this)
            {
                res = res && action.Apply(person);
            }

            return res;
        }

        #endregion // IPersonContainer


        #region IEnumerable

        public IEnumerator<IPerson> GetEnumerator()
        {
            return m_impl.Values.GetEnumerator();
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return m_impl.Values.GetEnumerator();
        }

        #endregion // IEnumerable


        #region Private

        private IDictionary<string, IPerson> m_impl
            = new Dictionary<string, IPerson>();

        #endregion // Private
    }
}
